import datetime
import math
import pyperclip
import pyautogui
import uiautomation as auto
import os
import time
from datetime import time
import subprocess
from pyautogui import *
from PIL import Image
import numpy as np
from paddleocr import PaddleOCR, draw_ocr
from configparser import ConfigParser



def get_curtime(time_format="%Y-%m-%d %H:%M:%S"):
    curTime = time.localtime()
    curTime = time.strftime(time_format, curTime)
    return curTime


def ocr_get_txt_pos(path="", text=""):
    '''
    获取文字与位置对应map
    :param path:图片路径，图片路径为空则默认获取当前屏幕截图
    :param text: 筛选需要查找的内容，匹配所有位置
    :return:list
    '''

    result, img_path = ocr_img_text(path, saveimg=True)

    print("图片识别结果保存：", img_path)

    poslist = [detection[0][0] for line in result for detection in line]
    txtlist = [detection[1][0] for line in result for detection in line]

    # 用list存文字与位置信息
    find_txt_pos = []

    items = 0

    if text == "":
        find_txt_pos = result
    else:
        for i in range(len(poslist)):
            if txtlist[i] == text or text in txtlist[i]:
                find_txt_pos.append(poslist[i])
                items += 1

    print(find_txt_pos)
    return find_txt_pos

#获取左下角的角标
def ocr_get_txt_pos_three(path="", text=""):
    '''
    获取文字与位置对应map
    :param path:图片路径，图片路径为空则默认获取当前屏幕截图
    :param text: 筛选需要查找的内容，匹配所有位置
    :return:list
    '''

    result, img_path = ocr_img_text(path, saveimg=True)

    print("图片识别结果保存：", img_path)

    poslist = [detection[0][2] for line in result for detection in line]
    txtlist = [detection[1][0] for line in result for detection in line]

    # 用list存文字与位置信息
    find_txt_pos = []

    items = 0

    if text == "":
        find_txt_pos = result
    else:
        for i in range(len(poslist)):
            if txtlist[i] == text or text in txtlist[i]:
                find_txt_pos.append(poslist[i])
                items += 1

    print(find_txt_pos)
    return find_txt_pos

#有些ocr识别有点不准确使用右角标位置
def ocr_get_txt_pos_right(path="", text="", ref=""):
    '''
    获取文字与位置对应map
    :param path:图片路径，图片路径为空则默认获取当前屏幕截图
    :param text: 筛选需要查找的内容，匹配所有位置
    :param ref: 参考对象
    :return:list
    '''

    result, img_path = ocr_img_text(path, saveimg=True)

    print("图片识别结果保存：", img_path)

    poslist = [detection[0][1] for line in result for detection in line]
    txtlist = [detection[1][0] for line in result for detection in line]

    # 用list存文字与位置信息
    find_txt_pos = []
    find_txt_pos_ref = []

    items = 0

    if text == "":
        find_txt_pos = result
    elif ref == "":
        for i in range(len(poslist)):
            if txtlist[i] == text or text in txtlist[i]:
                find_txt_pos.append(poslist[i])
                items += 1
    else:
        # 获取参考对象的坐标
        for i in range(len(poslist)):
            if txtlist[i] == ref or ref in txtlist[i]:
                find_txt_pos_ref.append(poslist[i])
                print(poslist[i])
        # 获取需要点击的坐标
        for i in range(len(poslist)):
            if (txtlist[i] == text or text in txtlist[i]) and (poslist[i][1] < find_txt_pos_ref[0][1] + 20):
                find_txt_pos.append(poslist[i])
                print(poslist[i])
                items += 1

    print(find_txt_pos)
    return find_txt_pos

#专门用于用于点击进入应用的地址
def ocr_get_txt_pos_modify(path="", text=""):
    '''
    获取文字与位置对应map
    :param path:图片路径，图片路径为空则默认获取当前屏幕截图
    :param text: 筛选需要查找的内容，匹配所有位置
    :return:list
    '''

    result, img_path = ocr_img_text(path, saveimg=True)

    print("图片识别结果保存：", img_path)

    poslist = [detection[0][0] for line in result for detection in line]
    poslistEnd = [detection[0][1] for line in result for detection in line]
    txtlist = [detection[1][0] for line in result for detection in line]

    # 用list存文字与位置信息
    find_txt_pos = []

    items = 0

    if text == "":
        find_txt_pos = result
    else:
        for i in range(len(poslist)):
            if txtlist[i] == text or text in txtlist[i]:
                find_txt_pos.append(poslist[i])
                find_txt_pos.append(poslistEnd[i])
                items += 1

    print(find_txt_pos)
    return find_txt_pos

#使用两个元素的比例来确定位置
def ocr_get_txt_pos_prop(path="", text="固定", fromText="", endText=""):
    '''
    获取文字与位置对应map
    :param path:图片路径，图片路径为空则默认获取当前屏幕截图
    :param text: 筛选需要查找的内容，匹配所有位置
    :param fromText: 筛选需要查找的内容，匹配所有位置
    :param endText: 筛选需要查找的内容，匹配所有位置
    :return:list
    '''

    result, img_path = ocr_img_text(path, saveimg=True)

    print("图片识别结果保存：", img_path)

    poslist = [detection[0][0] for line in result for detection in line]
    # poslistEnd = [detection[0][1] for line in result for detection in line]
    txtlist = [detection[1][0] for line in result for detection in line]

    # 用list存文字与位置信息
    find_txt_pos = []
    # find_txt_pos_end = []

    items = 0

    if text == "":
        find_txt_pos = result
    else:
        for i in range(len(poslist)):
            #两个元素必须相邻位置
            if (txtlist[i] == fromText or fromText in txtlist[i]) and (txtlist[i + 2] == endText or endText in txtlist[i + 2]):
                find_txt_pos.append(poslist[i])
                find_txt_pos.append(poslist[i + 2])
                items += 1

    print(find_txt_pos)
    return find_txt_pos

#识别图片文字
def ocr_img_text(path="", saveimg=False, printResult=False):
    '''
    图像文字识别
    :param path: 图片路径，为空则默认获取当前屏幕截图
    :param saveimg: 是否保存识别结果为图片
    :param printResult: 是否打印识别结果
    :return: 识别结果, 保存的图片名称
    '''
    # 初始化变量
    img_data = None
    img_name = "ImgTextOCR-img-" + get_curtime("%Y%m%d%H%M%S") + ".jpg"
    ocr_result = []
    boxes, txts, scores = [], [], []

    try:
        # 图片路径为空则默认获取屏幕截图
        if not path:
            img_data = np.array(screenshot())
        else:
            # 打开并转换图片格式
            with Image.open(path) as img:
                img_data = img.convert('RGB')

        # 初始化OCR模型
        ocr = PaddleOCR(use_angle_cls=True, lang="ch")
        ocr_result = ocr.ocr(img_data, cls=True)

        # 构造boxes, txts, scores列表
        for line in ocr_result:
            for detection in line:
                boxes.append(detection[0])
                txts.append(detection[1][0])
                scores.append(detection[1][1])

        # 打印识别结果
        if printResult:
            for line in ocr_result:
                for word in line:
                    print(word)

        # 保存识别结果为图片
        if saveimg:
            im_show = draw_ocr(img_data, boxes, txts, scores)
            im_show = Image.fromarray(im_show)
            im_show.save(img_name)

    except Exception as e:
        print(f"Error occurred during OCR processing: {e}")

    finally:
        # 清理资源，如需要的话关闭图像文件等（此处已使用with语句自动管理）
        pass

    return ocr_result, img_name
#获取坐标
def getCoordinate(text="", type="", endText="", prop=0.000001, ref=""):
    '''
    获取坐标
    :param text: 筛选需要查找的内容，匹配所有位置
    :param type: 类型，prop代表使用像素比例进行定位
    :param endText: text = fromText 结束文本
    :param prop: 像素比例    0.5
    :return:list
    '''
    # #获取当前界面截图元素
    # ocr_img_text(saveimg=True, printResult=True)
    #获取登录应用界面数据
    if type == "":
        if text == "172.88.1.61:89":
            pos_list = ocr_get_txt_pos_modify(text="172.88.1.61:89")
            pos_xOne, pos_yOne = pos_list[0]
            pos_xTwo, pos_yTwo = pos_list[1]
            res = [(pos_xOne + pos_xTwo) / 2, pos_yOne - 50]
            return res
        elif text == "审核":
            pos_list = ocr_get_txt_pos_right(text=text)
            pos_x, pos_y = pos_list[0]
            return [pos_x-10, pos_y+5]
        else:
            pos_list = ocr_get_txt_pos(text=text)
            pos_x, pos_y = pos_list[0]
            return [pos_x + 5, pos_y + 5]
    elif type == "right":
        pos_list = ocr_get_txt_pos_right(text=text, ref=ref)
        pos_x, pos_y = pos_list[0]
        return [pos_x, pos_y + 10]
    elif type == "prop":#使用像素比例进行定位--用于一些识别不到的符合
        pos_list = ocr_get_txt_pos_prop(fromText=text, endText=endText)
        pos_x_from, pos_y_from = pos_list[0]
        pos_x_end, pos_y_end = pos_list[1]
        return [int(math.floor((pos_x_end - pos_x_from) * prop)) + 5, pos_y_from + 5]
    else:
        pass

#点击元素
def elementClick(element:str):
    pos = getCoordinate(element)
    X = int(math.floor(pos[0]))
    Y = int(math.floor(pos[1]))
    auto.Click(X, Y, waitTime=1)

def elementClick_right(element:str):
    pos = getCoordinate(element,type="right")
    X = int(math.floor(pos[0]))
    Y = int(math.floor(pos[1]))
    auto.Click(X, Y, waitTime=1)

def elementDClick(element:str):
    pos = getCoordinate(element)
    X = int(math.floor(pos[0]))
    Y = int(math.floor(pos[1]))
    auto.Click(X, Y, waitTime=1)
    auto.Click(X, Y, waitTime=1)

#获取config.ini配置信息
def getIni(section:str, key:str) -> str:
    '''
    获取配置文件信息
    :param section: name of the section
    :param key: name of the key
    :return:
    '''
    conf = ConfigParser()
    conf.read("D:\pyconfig\config.ini","utf-8")
    # print(conf.has_section(section))
    if conf.has_section(section):
        return conf.get(section, key)
    else:
        return "没有值"

#自动化工作--自动审核或者记账
def autoWork(textElement=""):
    # 关闭UClient The process name to be brought to an abrupt halt
    process_name = "UClient.exe"

    # Employing the taskkill command to terminate the process
    os.system(f"taskkill /f /im {process_name}")

    #打开软件
    url = getIni("UClient", "url")
    print(url)
    subprocess.Popen(url)

    #窗口捕获
    window = auto.WindowControl(searchDepth=1, ClassName='YonyouUWnd')

    #线程强制停止，防止截图识别功能同步进行
    time.sleep(3)

    #1、单击应用
    # 左键单击事件auto.Click(x: int, y: int, waitTime: float = OPERATION_WAIT_TIME)
    pos = getCoordinate("172.88.1.61:89")
    X = int(math.floor(pos[0]))
    Y = int(math.floor(pos[1]))
    # auto.Click(1726, 950, waitTime = 1)
    auto.Click(X, Y, waitTime = 1)
    # auto.Click(150, 13, waitTime = 1)

    # [[[55.0, 458.0], [196.0, 463.0], [195.0, 491.0], [54.0, 486.0]], ('172.88.1.61:89', 0.9989128708839417)]
    # [[55.0, 460.0], [196.0, 465.0]]


    #线程强制停止，防止截图识别功能同步进行
    time.sleep(30)

    #获取当前时间来定位日期这个选择框
    text = str(datetime.datetime.now().date())
    print(text)
    #定位日期坐标位置
    elementClick_right(text)

    # 输入enter事件来定位用户
    auto.SendKeys('{ENTER}')

    #操作键盘
    auto.SendKeys('{2 1}{0 1}{1 1}{7 1}{0 3}{8 1}{7 1}{6 1}')

    #输入enter事件来定位密码
    auto.SendKeys('{ENTER}')

    #操作键盘
    auto.SendKeys('{h 1}{q 1}{2 1}{0 1}{2 1}{4 1}')

    #输入enter事件来点击登录
    auto.SendKeys('{ENTER}')

    time.sleep(2)

    #输入enter事件来点击账套登录
    auto.SendKeys('{ENTER}')

    #输入enter事件来点击公司
    auto.SendKeys('{ENTER}')

    #输入enter事件来点击登录
    auto.SendKeys('{ENTER}')

    time.sleep(2)

    #输入enter事件来点击强制登录
    auto.SendKeys('{ENTER}')

    #线程强制停止，防止截图识别功能同步进行
    time.sleep(10)

    #3、进入主界面开始执行相关业务
    #点击财务会计
    res = elementClick("财务会计")
    #点击总账
    res = elementClick("总账")
    #点击凭证管理
    pos = getCoordinate("凭证管理")
    X = int(math.floor(pos[0]))
    Y = int(math.floor(pos[1]))
    auto.Click(X-20, Y, waitTime = 1)
    #点击审核
    pos = getCoordinate(textElement)
    X = int(math.floor(pos[0]))
    Y = int(math.floor(pos[1]))
    pyautogui.click(X, Y, clicks=2, interval=0.1, duration=3.0)
    #线程强制停止，防止截图识别功能同步进行
    time.sleep(10)
    #点击查询
    res = elementClick("查询卡片显示")
    # auto.SendKeys('{F3}')
    #线程强制停止，防止截图识别功能同步进行
    time.sleep(5)

    #输入enter事件来点击主体账簿
    auto.SendKeys('{ENTER}')
    time.sleep(0.5)

    #全选当前账套，后续要ctrl+v
    auto.SendKeys('{Ctrl}(A)')
    time.sleep(0.5)

    # 将规定复制到系统剪贴板，同时将主体账簿复制进去
    pyperclip.copy('HQA-0002,HNY-0002,HQJ-0002,HQS-0002,SCW-0002,SDX（旧）-0002,SGY-0002,SHQ-0002,SQH-0002,SQZ-0002,SSD-0002,SWY-0002,SZX-0002,YTZ-0002,ZYX-0002,HQB-0002')  # 将规定复制到系统剪贴板#
    time.sleep(0.5)
    auto.SendKeys('{Ctrl}(V)')
    time.sleep(0.5)

    # 输入enter事件来点击会计期间
    auto.SendKeys('{Tab}')
    time.sleep(0.5)
    auto.SendKeys('{Tab}')
    time.sleep(0.5)
    auto.SendKeys('{Tab}')
    time.sleep(0.5)
    auto.SendKeys('{Tab}')
    time.sleep(0.5)
    auto.SendKeys('{Tab}')
    time.sleep(0.5)
    auto.SendKeys('{Tab}')
    time.sleep(0.5)
    auto.SendKeys('{Tab}')
    time.sleep(0.5)
    auto.SendKeys('{Tab}')
    time.sleep(2)



    #选择2023-02
    auto.SendKeys('{DOWN}')
    time.sleep(2)

    # # 此处有点异常-----------------enter事件异常修正
    # try:
    #     pos = getCoordinate("2023")
    # except Exception as e:
    #     # 此处有点异常-----------------
    #     auto.SendKeys('{ENTER}')
    #     time.sleep(2)
    #     # 选择2023-02
    #     auto.SendKeys('{DOWN}')
    #     time.sleep(2)

    auto.SendKeys('{UP}')
    time.sleep(2)
    auto.SendKeys('{ENTER}')
    time.sleep(2)
    auto.SendKeys('{DOWN 2}')
    time.sleep(2)
    auto.SendKeys('{ENTER}')
    time.sleep(2)

    #点击错误凭证
    # elementClick("错误凭证")
    auto.SendKeys('{Tab}')
    time.sleep(0.5)
    auto.SendKeys('{Tab}')
    time.sleep(0.5)
    auto.SendKeys('{Tab}')
    time.sleep(0.5)
    auto.SendKeys('{Tab}')
    time.sleep(0.5)
    auto.SendKeys('{Tab}')
    time.sleep(0.5)
    auto.SendKeys('{Tab}')
    time.sleep(0.5)
    auto.SendKeys('{Tab}')
    time.sleep(0.5)
    auto.SendKeys('{Tab}')
    time.sleep(0.5)
    auto.SendKeys('{Tab}')
    time.sleep(0.5)
    auto.SendKeys('{SPACE}')
    time.sleep(0.5)
    #点击作废凭证
    # elementClick("作废凭证")
    auto.SendKeys('{Tab}')
    time.sleep(0.5)
    auto.SendKeys('{SPACE}')
    time.sleep(0.5)

    #点击确认
    elementClick("确定")

    time.sleep(10)

    #点击审核数据第一行

    # pos = ocr_get_txt_pos_three(text="主体账簿")
    # pos_x, pos_y = pos[0]
    # X = int(math.floor(pos_x))
    # Y = int(math.floor(pos_y))
    # auto.Click(X + 5, Y + 20, waitTime = 1)

    auto.SendKeys('{Tab 7}')


    #选中多行
    pyautogui.keyDown('shiftleft')
    pyautogui.keyDown('shiftright')
    time.sleep(0.1)
    pyautogui.press(['down', 'down'])
    pyautogui.keyUp('shiftleft')
    pyautogui.keyUp('shiftright')

    #可以换成ctrl+A全选

    time.sleep(3)

    if textElement == "审核":
        #点击批审批 ctrl+U
        auto.SendKeys('{Ctrl}(U)')
        time.sleep(5)
    else:
        # 点击批记账 ctrl+U
        auto.SendKeys('{Ctrl}(L)')
        time.sleep(5)



if __name__ == '__main__':

    #首先进入审核
    autoWork("审核")

    #再记账
    autoWork("记账")

    # print(getIni("UClient", "url"))







